Fix the cirrus vga model to not leak memory when switching between
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 12 May 2006 14:17:21 +0000 (15:17 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 12 May 2006 14:17:21 +0000 (15:17 +0100)
initial vga mode and linear framebuffer.

When creating device model, the vga memory is allocated through
xc_domain_memory_increase_reservation(), however, when switch to use
linear framebuffer, we didn't free that memory, and re-allocate the vga
memory through set_mm_mapping(), that caused memory leak. Now it is
changed to just using qemu_malloc when create device model, and free
that memory when switch to linear framebuffer.

After unset_vram_mapping(), the old memory pointer should be
unmapped; after set_vram_mapping(), the old memory should be freed.

Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
tools/ioemu/hw/cirrus_vga.c
tools/ioemu/hw/pc.c
tools/ioemu/hw/vga.c
tools/ioemu/hw/vga_int.h
tools/ioemu/vl.c

index 80fd981df71a1867abc42546ec9736cd4db3be2d..8f3ac73d2618827e440f7d4e165bf993cfc93ce6 100644 (file)
@@ -272,7 +272,8 @@ typedef struct CirrusVGAState {
     int last_hw_cursor_y_end;
     int real_vram_size; /* XXX: suppress that */
     CPUWriteMemoryFunc **cirrus_linear_write;
-    int set_mapping;
+    unsigned long map_addr;
+    unsigned long map_end;
 } CirrusVGAState;
 
 typedef struct PCICirrusVGAState {
@@ -2543,12 +2544,12 @@ static int unset_vram_mapping(unsigned long begin, unsigned long end)
 static void * set_vram_mapping(unsigned long addr, unsigned long end) {}
 static int unset_vram_mapping(unsigned long addr, unsigned long end) {}
 #endif
+extern int vga_accelerate;
 
 /* Compute the memory access functions */
 static void cirrus_update_memory_access(CirrusVGAState *s)
 {
     unsigned mode;
-    extern int vga_accelerate;
 
     if ((s->sr[0x17] & 0x44) == 0x44) {
         goto generic_io;
@@ -2563,18 +2564,21 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
 
     mode = s->gr[0x05] & 0x7;
     if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
-            if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) {
-                if (!s->set_mapping) {
-                    void * vram_pointer;
-                    s->set_mapping = 1;
-                    vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
-                    if (!vram_pointer){
+            if ( vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end ) {
+                if (!s->map_addr) {
+                    void *vram_pointer, *old_vram;
+
+                    vram_pointer =
+                      set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end);
+                    if (!vram_pointer) {
                         fprintf(stderr, "NULL vram_pointer\n");
-                    } else
-                    {
-                        vga_update_vram((VGAState *)s, vram_pointer,
+                    } else {
+                        old_vram = vga_update_vram((VGAState *)s, vram_pointer,
                                         VGA_RAM_SIZE);
+                        qemu_free(old_vram);
                     }
+                    s->map_addr = s->cirrus_lfb_addr;
+                    s->map_end = s->cirrus_lfb_end;
                 }
             }
             s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
@@ -2583,13 +2587,19 @@ static void cirrus_update_memory_access(CirrusVGAState *s)
         } else {
         generic_io:
             if (vga_accelerate && s->cirrus_lfb_addr && s->cirrus_lfb_end) {
-                if(s->set_mapping) {
+                if(s->map_addr) {
                     int error;
-                    s->set_mapping = 0;
+                    void *old_vram = NULL;
+
                     error = unset_vram_mapping(s->cirrus_lfb_addr,
                                            s->cirrus_lfb_end);
                     if (!error)
-                        vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+                        old_vram =
+                          vga_update_vram((VGAState *)s, NULL, VGA_RAM_SIZE);
+
+                    if (old_vram)
+                        munmap(old_vram, s->map_addr - s->map_end);
+                    s->map_addr = s->map_end = 0;
                 }
             }
 
@@ -3184,6 +3194,12 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
                                 s->cirrus_linear_io_addr);
     s->cirrus_lfb_addr = addr;
     s->cirrus_lfb_end = addr + VGA_RAM_SIZE;
+
+    if ( vga_accelerate && s->map_addr &&
+         (s->cirrus_lfb_addr != s->map_addr) &&
+         (s->cirrus_lfb_end != s->map_end))
+        fprintf(logfile, "cirrus vga map change while on lfb mode\n");
+
     cpu_register_physical_memory(addr + 0x1000000, 0x400000,
                                 s->cirrus_linear_bitblt_io_addr);
 }
index 474b1de4f4ff43e423ed908cf55ccdfe69ecdf6d..40cbc826a48b33807a87f91200aad44f8cbdf0cf 100644 (file)
@@ -385,7 +385,6 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
     char buf[1024];
     int ret, linux_boot, initrd_size, i, nb_nics1;
     PCIBus *pci_bus;
-    extern void * shared_vram;
     
     linux_boot = (kernel_filename != NULL);
 
@@ -512,14 +511,14 @@ void pc_init(uint64_t ram_size, int vga_ram_size, int boot_device,
     if (cirrus_vga_enabled) {
         if (pci_enabled) {
             pci_cirrus_vga_init(pci_bus, 
-                                ds, shared_vram, ram_size, 
+                                ds, NULL, ram_size, 
                                 vga_ram_size);
         } else {
-            isa_cirrus_vga_init(ds, shared_vram, ram_size, 
+            isa_cirrus_vga_init(ds, NULL, ram_size, 
                                 vga_ram_size);
         }
     } else {
-        vga_initialize(pci_bus, ds, shared_vram, ram_size, 
+        vga_initialize(pci_bus, ds, NULL, ram_size, 
                        vga_ram_size);
     }
 
index c04befca3bb420106664a134440e165eb4b2a6ee..2d9e6449bf418e574ac9e79688da388b0a4e597c 100644 (file)
@@ -1946,11 +1946,11 @@ void vga_bios_init(VGAState *s)
 
 }
 
+/* when used on xen environment, the vga_ram_base is not used */
 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
                      unsigned long vga_ram_offset, int vga_ram_size)
 {
     int i, j, v, b;
-    extern void* shared_vram;
 
     for(i = 0;i < 256; i++) {
         v = 0;
@@ -1979,11 +1979,7 @@ void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
 
     /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort
      * when guest write vga mem, so allocate a new one */
-#if defined(__i386__) || defined(__x86_64__)
-    s->vram_ptr = shared_vram;
-#else
     s->vram_ptr = qemu_malloc(vga_ram_size);
-#endif
     check_sse2();
     s->vram_shadow = qemu_malloc(vga_ram_size+TARGET_PAGE_SIZE+1);
     if (s->vram_shadow == NULL)
@@ -2090,12 +2086,14 @@ int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
     return 0;
 }
 
-int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
 {
+    uint8_t *old_pointer;
+
     if (s->vram_size != vga_ram_size)
     {
         fprintf(stderr, "No support to change vga_ram_size\n");
-        return -1;
+        return NULL;
     }
 
     if ( !vga_ram_base )
@@ -2104,15 +2102,16 @@ int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
         if (!vga_ram_base)
         {
             fprintf(stderr, "reallocate error\n");
-            return -1;
+            return NULL;
         }
     }
 
     /* XXX lock needed? */
     memcpy(vga_ram_base, s->vram_ptr, vga_ram_size);
+    old_pointer = s->vram_ptr;
     s->vram_ptr = vga_ram_base;
 
-    return 0;
+    return old_pointer;
 }
 
 /********************************************************/
index 1789df51e6aa2bb0bf6e509592a38f6413555e6d..5a116f58ac4d0dfd85307dbcef5b7d9173600def 100644 (file)
@@ -165,6 +165,6 @@ void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
                              unsigned int color0, unsigned int color1,
                              unsigned int color_xor);
 
-int vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
+void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size);
 extern const uint8_t sr_mask[8];
 extern const uint8_t gr_mask[16];
index 6b60df6d4b678cd4c3de3fc3d6fae90fcb9e8c0c..54ec0967fcf115176de3508d713e5cdbd65c4f4c 100644 (file)
@@ -147,12 +147,6 @@ int repeat_key = 1;
 TextConsole *vga_console;
 CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 int xc_handle;
-unsigned long *vgapage_array;
-unsigned long *freepage_array;
-unsigned long free_pages;
-void *vtop_table;
-unsigned long toptab;
-unsigned long vgaram_pages;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -2454,32 +2448,6 @@ static uint8_t *signal_stack;
 
 #include <xg_private.h>
 
-#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
-#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
-
-#ifdef __i386__
-#define _LEVEL_3_ 0
-#else
-#define _LEVEL_3_ 1
-#endif
-
-#if _LEVEL_3_
-#define L3_PROT (_PAGE_PRESENT)
-#define L1_PAGETABLE_ENTRIES    512
-#else
-#define L1_PAGETABLE_ENTRIES    1024
-#endif
-
-inline int
-get_vl2_table(unsigned long count, unsigned long start)
-{
-#if _LEVEL_3_
-    return ((start + (count << PAGE_SHIFT)) >> L3_PAGETABLE_SHIFT) & 0x3;
-#else
-    return 0;
-#endif
-}
-
 /* FIXME Flush the shadow page */
 int unset_mm_mapping(int xc_handle,
                      uint32_t domid,
@@ -2584,10 +2552,8 @@ int main(int argc, char **argv)
     int serial_device_index;
     char qemu_dm_logfilename[64];
     const char *loadvm = NULL;
-    unsigned long nr_pages, extra_pages, ram_pages, *page_array;
-    xc_dominfo_t info;
+    unsigned long nr_pages, *page_array;
     extern void *shared_page;
-    extern void *shared_vram;
 
 #if !defined(CONFIG_SOFTMMU)
     /* we never want that malloc() uses mmap() */
@@ -3045,29 +3011,10 @@ int main(int argc, char **argv)
     /* init the memory */
     phys_ram_size = ram_size + vga_ram_size + bios_size;
 
-    ram_pages = ram_size/PAGE_SIZE;
-#if defined(__i386__) || defined(__x86_64__)
-    vgaram_pages =  (vga_ram_size -1) / PAGE_SIZE + 1;
-    free_pages = vgaram_pages / L1_PAGETABLE_ENTRIES;
-    extra_pages = vgaram_pages + free_pages;
-#else
-    /* Test vga acceleration later */
-    extra_pages = 0;
-#endif
+    nr_pages = ram_size/PAGE_SIZE;
 
     xc_handle = xc_interface_open();
 
-    xc_domain_getinfo(xc_handle, domid, 1, &info);
-
-    nr_pages = info.nr_pages + extra_pages;
-
-    if ( xc_domain_setmaxmem(xc_handle, domid,
-                             (nr_pages) * PAGE_SIZE/1024 ) != 0)
-    {
-        fprintf(logfile, "set maxmem returned error %d\n", errno);
-        exit(-1);
-    }
-
     if ( (page_array = (unsigned long *)
                         malloc(nr_pages * sizeof(unsigned long))) == NULL)
     {
@@ -3075,24 +3022,16 @@ int main(int argc, char **argv)
         exit(-1);
     }
 
-    if (xc_domain_memory_increase_reservation(xc_handle, domid,
-                                              extra_pages , 0, 0, NULL) != 0)
-    {
-        fprintf(logfile, "increase reservation returned error %d\n", errno);
-        exit(-1);
-    }
-
 #if defined(__i386__) || defined(__x86_64__)
     if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
     {
         fprintf(logfile, "xc_get_pfn_list returned error %d\n", errno);
         exit(-1);
     }
-
     if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
                           PROT_READ|PROT_WRITE,
                           page_array,
-                          ram_pages - 1)) == 0 )
+                          nr_pages - 1)) == 0 )
     {
         fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
         exit(-1);
@@ -3100,31 +3039,11 @@ int main(int argc, char **argv)
 
     shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
                                        PROT_READ|PROT_WRITE,
-                                       page_array[ram_pages - 1]);
-
-    vgapage_array = &page_array[nr_pages - vgaram_pages];
-
-    if ( (shared_vram =  xc_map_foreign_batch(xc_handle, domid,
-                                              PROT_READ|PROT_WRITE,
-                                              vgapage_array,
-                                              vgaram_pages)) == 0)
-    {
-        fprintf(logfile,
-                "xc_map_foreign_batch vgaram returned error %d\n", errno);
-        exit(-1);
-    }
-
-    memset(shared_vram, 0, vgaram_pages * PAGE_SIZE);
-    toptab = page_array[ram_pages] << PAGE_SHIFT;
-
-    vtop_table = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
-                                      PROT_READ|PROT_WRITE,
-                                      page_array[ram_pages]);
+                                       page_array[nr_pages - 1]);
 
-    freepage_array = &page_array[nr_pages - extra_pages];
 #elif defined(__ia64__)
-    if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, ram_pages)
-         != ram_pages )
+    if ( xc_ia64_get_pfn_list(xc_handle, domid, page_array, 0, nr_pages)
+         != nr_pages)
     {
         fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno);
         exit(-1);
@@ -3133,7 +3052,7 @@ int main(int argc, char **argv)
     if ( (phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
                           PROT_READ|PROT_WRITE,
                           page_array,
-                          ram_pages)) == 0 )
+                          nr_pages)) == 0 )
     {
         fprintf(logfile, "xc_map_foreign_batch returned error %d\n", errno);
         exit(-1);
@@ -3141,7 +3060,7 @@ int main(int argc, char **argv)
 
     if ( xc_ia64_get_pfn_list(xc_handle, domid,
                               page_array,
-                              ram_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 )
+                              nr_pages + (GFW_SIZE >> PAGE_SHIFT), 1) != 1 )
     {
         fprintf(logfile, "xc_ia64_get_pfn_list returned error %d\n", errno);
         exit(-1);